let tokenTypes = require('../common/token-types');
let astModule = require('../modules/ast-module');
let astNodeTags = require('../common/ast-node-tags');
let nodeUtil = require('../common/node-util');

let operatorParser = {
  nodeStack: [],
  operatorStack: [],
  children: [],
  operator: {},
  params: [],
  result: {},
  parse(tokens) {
    this.children = tokens.slice(0);
    let endIndex = tokens.length;
    this.operator = tokens.shift();
    tokens.forEach((token, index) => {
      if ([tokenTypes.DIGIT, tokenTypes.WORD].includes(token.type)) {
        if (this.nodeStack.length == 0) {
          this.nodeStack.push(nodeUtil.genLiteralNode(token));
        } else {
          if (this.operatorStack.length == 0) {
            this.params.push(nodeUtil.genLiteralNode(this.nodeStack.pop()));
            this.nodeStack.push(nodeUtil.genLiteralNode(token));
          } else {
            let left = this.nodeStack.pop();
            let right = nodeUtil.genLiteralNode(token);
            let operator = this.operatorStack.pop();
            this.params.push(this.genNodeForExp(left, right, operator, 0, 0));
          }
        }
      } else {
        this.operatorStack.push(token);
      }
    });
    if (this.nodeStack.length > 0) {
      this.params.push(nodeUtil.genLiteralNode(this.nodeStack.pop()));
    }
    return new astModule.Operator(astNodeTags.OPERA, this.params, this.operator, this.children, 0, endIndex);
  },
  genNodeForExp(left, right, operator, start, end) {
    let tag = nodeUtil.getExpTag(operator);
    let children = [left.value].concat(operator).concat(right.value);
    return new astModule.Expression(tag, left, right, operator, children, start, end);
  }
};

module.exports = operatorParser;
